package com.zhoug.zmui.utils;

import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Xfermode;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;

import com.zhoug.common.utils.CanvasUtils;
import com.zhoug.common.utils.LogUtils;
import com.zhoug.zmui.R;
import com.zhoug.zmui.utils.ZMUIUtils;

import java.lang.ref.WeakReference;

import androidx.annotation.AttrRes;
import androidx.annotation.RequiresApi;
import androidx.annotation.StyleRes;

/**
 * ZMUIView自定义属性工具类
 * *
 * 支持圆角组件,支持边界
 * * 在View的对应方法中调用同名方法
 *
 * @Author 35574
 * @Date 2020/7/23
 * @Description
 */
public class ZMUIViewHelper {
    private static final String TAG = ">>>ZMUIViewHelper";
    private static final boolean DEBUG = false;

    /***角度*/
    private int corners;
    /***是否为圆形:为true时corners属性无效*/
    private boolean isRound;
    /***边界尺寸**/
    private int border;
    /***边界颜色**/
    private int borderColor;
    /***边界按下后的颜色**/
    private int borderColorPressed;


    //半径
    private float mRadius;
    // 圆形路径
    private Path mRoundPath;
    private Paint mPaint;
    private Bitmap mCacheBitmap;
    private Xfermode DEST_IN = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
    //显示的边界颜色
    private int mCurBorderColor;
    //边界路径
    private Path mBorderPath;

    public ZMUIViewHelper(View target) {
        //画笔
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        //硬件加速,否则会有黑色背景
        target.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

    /**
     * 解析出属性
     *
     * @param context      context
     * @param attrs        AttributeSet
     * @param defStyleAttr R.attr
     * @param defStyleRes  R.style
     */
    public void parseAttribute(Context context, AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ZMUIViewHelper, defStyleAttr, defStyleRes);
        isRound = a.getBoolean(R.styleable.ZMUIViewHelper_zmui_isRound, false);
        corners = a.getDimensionPixelOffset(R.styleable.ZMUIViewHelper_zmui_corners, 0);
        border = a.getDimensionPixelOffset(R.styleable.ZMUIViewHelper_zmui_border, 0);
        ColorStateList colorStateList = a.getColorStateList(R.styleable.ZMUIViewHelper_zmui_borderColor);
        if (colorStateList != null) {
            int[] statePress = new int[]{android.R.attr.state_pressed};
            int[] stateNormal = new int[]{};
            borderColor = colorStateList.getColorForState(stateNormal, ZMUIUtils.UN_USED_COLOR);
            borderColorPressed = colorStateList.getColorForState(statePress, ZMUIUtils.UN_USED_COLOR);
            mCurBorderColor = borderColor;
        }
        a.recycle();
        if (DEBUG) {
            LogUtils.d(TAG, "parseAttribute:isRound=" + isRound);
            LogUtils.d(TAG, "parseAttribute:corners=" + corners);
            LogUtils.d(TAG, "parseAttribute:border=" + border);
            LogUtils.d(TAG, "parseAttribute:borderColor=" + Integer.toHexString(borderColor));
            LogUtils.d(TAG, "parseAttribute:borderColorPressed=" + Integer.toHexString(borderColorPressed));
        }
    }


    /**
     * 在 View.onSizeChanged(int, int, int, int)中调用
     *
     * @param width  {@link View#getWidth()}
     * @param height {@link View#getHeight()}
     */
    public void onSizeChanged(int width, int height) {
        //计算半径
        mRadius = width < height ? width >> 1 : height >> 1;
        //最大角度
        if (corners > mRadius) {
            corners = (int) mRadius;
        }
        //支持圆角
        if (supportRound()) {
            mRoundPath = getRoundPath(width, height);
            if (mRoundPath != null) {
                mPaint.setStyle(Paint.Style.FILL);
                mPaint.setXfermode(null);
                //创建一张和ImageView宽高尺寸相同的bitmap并画路径
                mCacheBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
                Canvas mCacheCanvas = new Canvas(mCacheBitmap);
                mCacheCanvas.drawPath(mRoundPath, mPaint);
            }
        }
        //支持边界
        if (supportBorder()) {
            mBorderPath = getBorderPath(width, height);
        }
    }

    /**
     * 是否支持圆角
     *
     * @return
     */
    private boolean supportRound() {
        return corners > 0 || isRound;
    }

    /***
     * 是否只支持边界
     * @return
     */
    private boolean supportBorder() {
        return border > 0;
    }


    /**
     * 在 View.onDraw中调用
     * eg: {
     * protected void onDraw(Canvas canvas) {
     * super.onDraw(canvas);
     * mRoundViewHelper.onDraw(canvas);
     * }
     * }
     *
     * @param canvas
     */
    public void onDraw(Canvas canvas) {
        //画圆角
        if (supportRound()) {
            if (DEBUG) {
                LogUtils.d(TAG, "画圆角");
            }
            mPaint.setXfermode(DEST_IN);
            canvas.drawBitmap(mCacheBitmap, 0, 0, mPaint);
        }
        //画边界
        if (supportBorder() && mCurBorderColor != ZMUIUtils.UN_USED_COLOR) {
            if (DEBUG) {
                LogUtils.d(TAG, "画边界" + Integer.toHexString(mCurBorderColor));
            }
            mPaint.setXfermode(null);
            mPaint.setStrokeWidth(border);
            mPaint.setColor(mCurBorderColor);
            mPaint.setStyle(Paint.Style.STROKE);
            canvas.drawPath(mBorderPath, mPaint);
        }
    }


    /**
     * 计算圆角路劲
     *
     * @return
     */
    private Path getRoundPath(int width, int height) {
        Path path = null;
        //圆
        if (isRound) {
            path = new Path();
            path.addCircle(width / 2, height / 2, mRadius, Path.Direction.CW);
        } else if (corners > 0) {
            //圆角
            path = new Path();
            path.moveTo(corners, 0);
            path.lineTo(width - corners, 0);
            //二次贝塞尔
            path.quadTo(width, 0, width, corners);
            path.lineTo(width, height - corners);
            path.quadTo(width, height, width - corners, height);
            path.lineTo(corners, height);
            path.quadTo(0, height, 0, height - corners);
            path.lineTo(0, corners);
            path.quadTo(0, 0, corners, 0);
        }
        return path;
    }

    /**
     * 计算边框路劲
     *
     * @return
     */
    private Path getBorderPath(int width, int height) {
        if (supportBorder()) {
            Path path = new Path();
            float b =  border/2.0f;

            //圆
            if (isRound) {
                path.addCircle(width >> 1, height >> 1, mRadius - b, Path.Direction.CW);
            } else if (corners > 0) {
                int c=corners;

                //圆角
                path = new Path();
                path.moveTo(c, b);
                path.lineTo(width - c, b);
                //二次贝塞尔
                path.quadTo(width-b, b, width-b, c);
                path.lineTo(width-b, height - c);
                path.quadTo(width-b, height-b, width - c, height-b);
                path.lineTo(c, height-b);
                path.quadTo(b, height-b, b, height - c);
                path.lineTo(b, c);
                path.quadTo(b, b, c, b);

            } else {
                path.addRect(b, b, width - b, height - b, Path.Direction.CW);
            }
            return path;
        }
        return null;
    }


    /**
     * 如果是圆形且宽高不相等则设置宽高为最短边的长度
     * 在View.onMeasure中调用,如果返回值大于0,则需要重新设置View的宽高View.setMeasuredDimension(size,size);
     *
     * @param measuredWidth
     * @param measuredHeight
     * @return size
     */
    public int measureSize(int measuredWidth, int measuredHeight) {
        if (isRound && measuredWidth != measuredHeight) {
            return Math.min(measuredWidth, measuredHeight);
        }
        return 0;
    }

    /**
     * 在 {@link View#setPressed(boolean)} 中调用，通知 helper 更新
     *
     * @param current the view to be handled, maybe not equal to target view
     * @param pressed {@link View#setPressed(boolean)} 中接收到的参数
     */
    public void onPressedChanged(View current, boolean pressed) {
        if (supportBorder() && borderColorPressed != ZMUIUtils.UN_USED_COLOR) {
            mCurBorderColor = pressed ? borderColorPressed : borderColor;
            if (mCurBorderColor != ZMUIUtils.UN_USED_COLOR) {
                current.invalidate();
            }
        }
    }

}
